package cn.wp.common.core.dto;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ClassUtil;
import cn.hutool.core.util.StrUtil;
import cn.wp.common.core.WpVar;
import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.Getter;
import lombok.Setter;

import java.io.Serializable;

/**
 * 响应结果数据传输对象
 * Created by chenyb on 2019/09/24
 */
public class WpResult<T> implements Serializable {

    private static final long serialVersionUID = 1L;

    /**
     * 封装业务时间
     */
    @Getter
    @Setter
    private String timestamp = DateUtil.now();

    /**
     * 状态码
     */
    @Getter
    @Setter
    private String code;

    /**
     * 消息
     */
    @Getter
    @Setter
    private String message;


    /**
     * 封装
     * 请求成功的数据库数据
     */
    @Getter
    @Setter
    private T dataBody;

    public WpResult() {
        super();
        success();
    }

    public static <T> WpResult suc(T dataBody){
        WpResult<T> result = new WpResult<>();
        return result.success(dataBody);
    }

    public static WpResult suc() {
        WpResult result = new WpResult<>();
        return result.success();
    }

    public static <T> WpResult fail(T dataBody){
        WpResult<T> result = new WpResult<>();
        return result.failure(dataBody);
    }

    public static WpResult fail() {
        WpResult result = new WpResult<>();
        return result.failure();
    }

    public WpResult success() {
        this.message = "success";
        this.code = WpVar.SUCCESS_CODE;
        return this;
    }

    public WpResult success(T dataBody) {
        this.code = WpVar.SUCCESS_CODE;
        this.dataBody = dataBody;
        return this;
    }

    public WpResult success(String message, Object dataBody) {
        this.message = message;
        this.code = WpVar.SUCCESS_CODE;
        return this;
    }

    public WpResult failure() {
        this.message = "failure";
        this.code = WpVar.DEFAULT_FAILURE_CODE;
        return this;
    }

    public WpResult failure(T code) {
        this.checkCodeValueIsBasic(code);
        this.code = StrUtil.toString(code);
        return this;
    }

    public WpResult failure(T code, String message) {
        this.checkCodeValueIsBasic(code);
        this.message = message;
        this.code = StrUtil.toString(code);
        return this;
    }

    public WpResult failure(T code, T dataBody) {
        this.checkCodeValueIsBasic(code);
        this.dataBody = dataBody;
        this.code = StrUtil.toString(code);
        return this;
    }

    public WpResult failure(T code, String message, T dataBody) {
        this.checkCodeValueIsBasic(code);
        this.dataBody = dataBody;
        this.message = message;
        this.code = StrUtil.toString(code);
        return this;
    }

    public WpResult error() {
        this.message = "error";
        this.code = WpVar.ERROR_CODE;
        return this;
    }

    public WpResult error(String message, T dataBody) {
        this.code = WpVar.ERROR_CODE;
        this.message = message;
        this.dataBody = dataBody;
        return this;
    }

    /**
     * 是否错误返回
     * @return
     */
    @JsonIgnore
    public boolean isError(){
        return WpVar.ERROR_CODE.equals(this.code);
    }

    /**
     * 是否成功返回
     * @return
     */
    @JsonIgnore
    public boolean isSuccess(){
        return WpVar.SUCCESS_CODE.equals(this.code);
    }

    /**
     * 是否鉴权相关失败
     * @return
     */
    @JsonIgnore
    public boolean isAuthFailure(){
        return WpVar.NO_LOGIN_CODE.equals(this.code)
                || WpVar.REPEAT_LOGIN_CODE.equals(this.code)
                || WpVar.TOKEN_INVALID_CODE.equals(this.code);
    }

    /**
     * 是否逻辑失败返回
     * @return
     */
    @JsonIgnore
    public boolean isFailure(){
        return !isSuccess() && !isError();
    }

    /**
     * 检查是否为基本类型
     * @param object
     * @return
     */
    private void checkCodeValueIsBasic(Object object){
        if(object == null){
            throw new IllegalArgumentException("code value can not be empty");
        }
        boolean isBasicType = ClassUtil.isBasicType(object.getClass());
        if(!isBasicType && object.getClass() != String.class){
            throw new IllegalArgumentException("code value must be a basic data type, but current code value type is "+ object.getClass().getName());
        }
    }

}
